package org.bambrikii.site.base.business.managers;

import java.util.HashMap;

import org.bambrikii.site.base.business.managers.core.ManagerException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ManagerContainer implements ApplicationContextAware {

	private ConnectionManager connectionManager;
	private ApplicationContext applicationContext;

	public ConnectionManager getConnectionManager() {
		return connectionManager;
	}

	public void setConnectionManager(ConnectionManager connectionManager) {
		this.connectionManager = connectionManager;
	}

	private HashMap<Class<?>, ManagerBase<?, ?>> managers = new HashMap<Class<?>, ManagerBase<?, ?>>();

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	public ManagerContainer() {
	}

	public ManagerContainer(String cfg) {
		applicationContext = new ClassPathXmlApplicationContext(cfg);
		connectionManager = (ConnectionManager) applicationContext.getBean(ConnectionManager.class.getSimpleName());
	}

	public static ManagerContainer getNewInstance(String cfg) {
		ManagerContainer mgr = new ManagerContainer(cfg);
		return mgr;
	}

	public void open() {
		connectionManager.open();
	}

	public void close() {
		connectionManager.close();
		connectionManager = null;
		// _inst = null;
	}

	public void begin() throws ManagerException {
		connectionManager.begin();
	}

	public void commit() {
		connectionManager.commit();
	}

	public void rollback() {
		connectionManager.rollback();
	}

	public <T extends ManagerBase<?, ?>> T getManager(Class<?> klz) throws ManagerException {
		if (!managers.containsKey(klz)) {
			ManagerBase<?, ?> mgr;
			try {
				// Constructor<?> constructor = klz
				// .getConstructor(new Class<?>[] { ConnectionManager.class });
				// mgr = (ManagerBase<?, ?>) constructor
				// .newInstance(new Object[] { cnMgr });
				mgr = (ManagerBase<?, ?>) applicationContext.getBean(klz.getSimpleName());
				// } catch (InstantiationException ex) {
				// throw new ManagerException(
				// "Cannnot instantiate Manager of type "
				// + klz.getCanonicalName(), ex);
				// } catch (IllegalAccessException ex) {
				// throw new ManagerException(
				// "Cannnot instantiate Manager of type "
				// + klz.getCanonicalName(), ex);
			} catch (SecurityException ex) {
				throw new ManagerException("Cannnot instantiate Manager of type " + klz.getCanonicalName(), ex);
				// } catch (NoSuchMethodException ex) {
				// throw new ManagerException(
				// "Cannnot instantiate Manager of type "
				// + klz.getCanonicalName(), ex);
			} catch (IllegalArgumentException ex) {
				throw new ManagerException("Cannnot instantiate Manager of type " + klz.getCanonicalName(), ex);
				// } catch (InvocationTargetException ex) {
				// throw new ManagerException(
				// "Cannnot instantiate Manager of type "
				// + klz.getCanonicalName(), ex);
			}
			managers.put(klz, (ManagerBase<?, ?>) mgr);
		}
		return (T) managers.get(klz);
	}
}
